package controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import model.CompletedItem;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import utils.DownloadImageTask;
import utils.XmlParser;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
import app.cloudstringers.Completed;
import app.cloudstringers.R;
import define.API;
import define.Constants;
import define.Key;

public class CompletedAsync extends AsyncTask<String, Void, Boolean> {

	/**
	 * String section
	 */
	// All static variables
	// XML node keys
	private static final String KEY_CONTENT_TYPE = "CONTENTTYPE";
	private static final String KEY_CURRENT_SIZE = "CURRENTSIZE";
	private static final String KEY_FILE = "FILE";
	private static final String KEY_FILE_NAME = "FILENAME";
	private static final String KEY_MEMO = "MEMO";
	private static final String KEY_STATE = "STATE";
	private static final String KEY_TOTAL_SIZE = "TOTALSIZE";
	private static final String KEY_UPLOAD_ID = "UPLOAD_ID";
	private static final String KEY_UPLOAD_TIME = "UPLOADTIME";
	private static final String KEY_PREVIEW_LINK = "VIDEO_PREVIEW";

	private String CONTENT_TYPE = null;
	private String CURRENT_SIZE = null;
	private String FILE_NAME = null;
	private String ID = null;
	private String MEMO = null;
	private String PREVIEW_LINK = null;
	private String STATE = null;
	private String TOTAL_SIZE = null;
	private String UPLOAD_TIME = null;
	private String UPLOAD_ID = null;

	private static final String TAG = CompletedAsync.class.getSimpleName();

	/**
	 * Data section
	 */
	private ArrayList<CompletedItem> mAlItem = new ArrayList<CompletedItem>();
	private ItemAdapter itemAdapter;

	/**
	 * View section
	 */
	private ListView mLv;

	/**
	 * The Other Tools
	 */
	private Context context;
	private XmlParser mXMLParser;

	public CompletedAsync(Context context) {
		this.context = context;

		// Initial data
		itemAdapter = new ItemAdapter(context,
				R.layout.simple_list_item_completed, mAlItem);
	}

	@Override
	protected Boolean doInBackground(String... params) {
		ID = params[0];
		try {
			HttpClient mHttpClient = new DefaultHttpClient();
			HttpPost mHttpPost = new HttpPost(API.UPLOAD_STATUS);
			List<NameValuePair> mNameValues = new ArrayList<NameValuePair>(2);

			mNameValues.add(new BasicNameValuePair(Key.KEY_GLOBAL_ID, ID));
			mNameValues.add(new BasicNameValuePair(Key.KEY_STATE,
					Constants.STATE_DONE + ""));

			mHttpPost.setEntity(new UrlEncodedFormEntity(mNameValues));

			HttpResponse mHttpResponse = mHttpClient.execute(mHttpPost);
			HttpEntity mHttpEntity = mHttpResponse.getEntity();

			String XML = EntityUtils.toString(mHttpEntity);

			// Log.i(TAG, XML);

			mXMLParser = new XmlParser();
			Document mDocument = mXMLParser.getDomElement(XML);

			NodeList mNodeList = mDocument.getElementsByTagName(KEY_FILE);
			for (int i = 0; i < mNodeList.getLength(); i++) {
				if (mNodeList.item(i).getNodeType() == Node.ELEMENT_NODE) {
					Element element = (Element) mNodeList.item(i);

					CONTENT_TYPE = mXMLParser.getValue(element,
							KEY_CONTENT_TYPE);
					CURRENT_SIZE = mXMLParser.getValue(element,
							KEY_CURRENT_SIZE);
					FILE_NAME = mXMLParser.getValue(element, KEY_FILE_NAME);
					MEMO = mXMLParser.getValue(element, KEY_MEMO);
					PREVIEW_LINK = mXMLParser.getValue(element,
							KEY_PREVIEW_LINK);
					STATE = mXMLParser.getValue(element, KEY_STATE);
					TOTAL_SIZE = mXMLParser.getValue(element, KEY_TOTAL_SIZE);
					UPLOAD_ID = mXMLParser.getValue(element, KEY_UPLOAD_ID);
					UPLOAD_TIME = mXMLParser.getValue(element, KEY_UPLOAD_TIME);

					// Set data
					CompletedItem completedItem = new CompletedItem(
							CONTENT_TYPE, CURRENT_SIZE, FILE_NAME, MEMO,
							PREVIEW_LINK, STATE, TOTAL_SIZE, UPLOAD_ID,
							UPLOAD_TIME);

					// adding all the elements in photo at index 0
					mAlItem.add(completedItem);
				}
			}

			return true;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (ConnectTimeoutException e) {
			e.printStackTrace();
			return false;
		} catch (SocketException e) {
			e.printStackTrace();
			return false;
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();

		// show progress dialog
		Constants.utils.showProgressDialog();

		mLv = (ListView) ((Activity) context).findViewById(R.id.lv_in_completed);
	}

	@Override
	protected void onPostExecute(Boolean result) {
		super.onPostExecute(result);

		if (!result) {
			Constants.utils.showConnectionTimeoutDialog(context,
					Completed.class);
		} else {
			if (itemAdapter != null && !itemAdapter.isEmpty()) {
				mLv.setAdapter(itemAdapter);
				itemAdapter.notifyDataSetChanged();
			}

			/**
			 * Show memo dialog when clicked the item
			 */
			mLv.setOnItemClickListener(new OnItemClickListener() {

				@Override
				public void onItemClick(AdapterView<?> arg0, View v,
						int position, long arg3) {
					// New thread to refresh memo dialog
					new LoadDataAsync(context).execute(position);
				}
			});
		}

		// hide progress dialog
		Constants.utils.hideProgressDialog();
	}

	/**
	 * Initial methods
	 */
	private class LoadDataAsync extends AsyncTask<Integer, Void, Void> {
		/**
		 * String section
		 */
		private int position = 0;

		private String NEW_MEMO = null;
		private String NEW_TITLE = null;
		private String PREVIEW = null;

		/**
		 * View section
		 */
		private Dialog mDialogMemo;
		private EditText mEtDescription;
		private EditText mEtTitle;
		private ImageButton mIbtnPlayVideoInNormalScreen;
		private ImageButton mIbtnPlayVideoInFullScreen;
		private ImageView mIvShowPreview;
		private VideoView mVvPlayVideo;

		public LoadDataAsync(Context context) {
		}

		@Override
		protected Void doInBackground(Integer... params) {
			position = params[0];

			UPLOAD_ID = mAlItem.get(position).getUploadID();
			PREVIEW = mAlItem.get(position).getPreviewLink();

			return null;
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();

			Constants.utils.showProgressDialog();

			initialDialogs();

			// Initial source for dialog
			mDialogMemo.setContentView(R.layout.dialog_memo);

			// Initial full screen dialog
			Constants.utils.initialFullScreenDialog(mDialogMemo);

			// Initial variables
			initialVariables(mDialogMemo);

			// Initial Data
			initialData();
		}

		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);

			// get and show data follow position
			getData(Integer.valueOf(position));

			Constants.utils.hideProgressDialog();
		}

		/**
		 * Initial methods
		 */
		private void initialData() {
			MediaController controller = new MediaController(context);
			controller.setAnchorView(mVvPlayVideo);

			mVvPlayVideo.requestFocus();
			mVvPlayVideo.setBackgroundColor(Color.BLACK);
			mVvPlayVideo.setMediaController(controller);
			mVvPlayVideo.setZOrderOnTop(true);
			mVvPlayVideo.setOnTouchListener(new OnTouchListener() {

				@Override
				public boolean onTouch(View v, MotionEvent event) {
					if (mVvPlayVideo.isPlaying()) {
						mVvPlayVideo.pause();

						// Show full-screen button again
						mIbtnPlayVideoInFullScreen.setVisibility(View.VISIBLE);
					} else {
						mVvPlayVideo.start();
					}

					return false;
				}
			});
		}

		private void initialDialogs() {
			mDialogMemo = new Dialog(context);
		}

		private void initialVariables(Dialog dialog) {
			mEtDescription = (EditText) dialog
					.findViewById(R.id.et_description_in_memo);
			mEtTitle = (EditText) dialog.findViewById(R.id.et_title_in_memo);
			mIbtnPlayVideoInNormalScreen = (ImageButton) dialog
					.findViewById(R.id.ibtn_play_video_in_normal_screen_in_memo);
			mIbtnPlayVideoInFullScreen = (ImageButton) dialog
					.findViewById(R.id.ibtn_play_video_in_full_screen_in_memo);
			mIvShowPreview = (ImageView) dialog
					.findViewById(R.id.iv_play_video_in_memo);
			mVvPlayVideo = (VideoView) dialog
					.findViewById(R.id.vv_play_video_in_memo);
		}

		/**
		 * Basic methods
		 */
		private void getData(final int position) {
			// Set data for title & description
			mEtDescription.setText("" + mAlItem.get(position).getMemo());
			mEtTitle.setText("" + mAlItem.get(position).getFileName());

			/**
			 * Separate the photo and the video in here 0 - Video 1 - Photo
			 */
			if (mAlItem.get(position).getContentType()
					.equals(define.Completed.CONTENT_TYPE_PHOTO)) {
				// 1 - Photo
				mIbtnPlayVideoInNormalScreen.setVisibility(View.INVISIBLE);
				mIbtnPlayVideoInFullScreen.setVisibility(View.INVISIBLE);
				mIvShowPreview.setVisibility(View.VISIBLE);
				mVvPlayVideo.setVisibility(View.INVISIBLE);

				new DownloadImageTask(mIvShowPreview).execute(PREVIEW);
			} else {
				// 0 - Video
				mIbtnPlayVideoInNormalScreen.setVisibility(View.VISIBLE);
				mIbtnPlayVideoInFullScreen.setVisibility(View.VISIBLE);
				mIvShowPreview.setVisibility(View.INVISIBLE);
				mVvPlayVideo.setVisibility(View.VISIBLE);

				/**
				 * Play video in normal screen mode
				 */
				mIbtnPlayVideoInNormalScreen
						.setOnClickListener(new OnClickListener() {

							@Override
							public void onClick(View view) {
								mVvPlayVideo.setVisibility(View.VISIBLE);
								mIbtnPlayVideoInNormalScreen
										.setVisibility(View.INVISIBLE);
								mIbtnPlayVideoInFullScreen
										.setVisibility(View.INVISIBLE);
								/**
								 * Play video is not in Full-Screen Mode
								 */
								playVideoInNormalScreenMode(mAlItem.get(
										position).getPreviewLink());
							}
						});

				/**
				 * Play video in full screen mode
				 */
				mIbtnPlayVideoInFullScreen
						.setOnClickListener(new OnClickListener() {

							@Override
							public void onClick(View v) {
								playVideoInFullScreenMode(PREVIEW);
							}
						});
			}

			// Cancel button
			mDialogMemo.findViewById(R.id.ibtn_cancel_in_memo)
					.setOnClickListener(new OnClickListener() {

						@Override
						public void onClick(View v) {
							mDialogMemo.dismiss();
						}
					});

			// Save button
			mDialogMemo.findViewById(R.id.btn_save_all_info_in_memo)
					.setOnClickListener(new OnClickListener() {

						@Override
						public void onClick(View v) {
							saveData();
						}
					});

			// Show memo dialog
			mDialogMemo.show();
		}

		public Bitmap loadBitmap(String url) {
			Bitmap bitmap = null;
			InputStream in = null;
			BufferedOutputStream out = null;

			try {
				in = new BufferedInputStream(new URL(url).openStream(), 1024);

				final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
				// out = new BufferedOutputStream(dataStream, 1024);
				// copy(in, out);
				// out.flush();

				final byte[] data = dataStream.toByteArray();
				BitmapFactory.Options options = new BitmapFactory.Options();
				// options.inSampleSize = 1;

				bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,
						options);

				in.close();
			} catch (IOException e) {
				Log.e(TAG, "Could not load Bitmap from: " + url);
			}

			return bitmap;
		}

		private void playVideoInNormalScreenMode(String videoLink) {
			mVvPlayVideo.setBackgroundColor(Color.TRANSPARENT);
			mVvPlayVideo.setVideoURI(Uri.parse(videoLink));
			mVvPlayVideo.start();
		}

		private void playVideoInFullScreenMode(String VIDEO_LINK) {
			Intent intent = new Intent(Intent.ACTION_VIEW,
					Uri.parse(VIDEO_LINK));
			intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			intent.setDataAndType(Uri.parse(VIDEO_LINK), Constants.MIME_TYPE);
			context.startActivity(intent);
		}

		private void saveData() {
			// Show alert dialog, fill in the blank
			NEW_TITLE = mEtTitle.getText().toString();
			NEW_MEMO = mEtDescription.getText().toString();

			if (!NEW_TITLE.equals("")) {
				// Run new thread to store input data
				new SaveMemoInfoAsync(context).execute(ID, NEW_MEMO, NEW_TITLE,
						UPLOAD_ID);

				// Dismiss memo dialog
				mDialogMemo.dismiss();
			} else {
				Toast.makeText(context,
						context.getString(R.string.toast_fill_in_the_blank),
						Toast.LENGTH_SHORT).show();
			}
		}
	}

	private class ItemAdapter extends ArrayAdapter<CompletedItem> {

		private ArrayList<CompletedItem> items = new ArrayList<CompletedItem>();

		private LayoutInflater inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

		private class ViewHolder {
			TextView mTvFileName;
			TextView mTvDescription;
		}

		public ItemAdapter(Context context, int textViewResourceId,
				ArrayList<CompletedItem> items) {
			super(context, textViewResourceId, items);

			this.items = items;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder viewHolder = null;
			if (convertView == null) {
				viewHolder = new ViewHolder();
				convertView = inflater.inflate(
						R.layout.simple_list_item_completed, null);

				viewHolder.mTvFileName = (TextView) convertView
						.findViewById(R.id.tv_file_name_item_in_completed);
				viewHolder.mTvDescription = (TextView) convertView
						.findViewById(R.id.tv_description_item_in_completed);

				convertView.setTag(viewHolder);
			} else {
				viewHolder = (ViewHolder) convertView.getTag();
			}

			CompletedItem completedItem = items.get(position);
			if (completedItem != null) {
				viewHolder.mTvFileName.setText(completedItem.getFileName());
				viewHolder.mTvDescription
						.setText(completedItem.getUploadTime());
			}
			return convertView;
		}

		@Override
		public void unregisterDataSetObserver(DataSetObserver observer) {
			if (observer != null) {
				super.unregisterDataSetObserver(observer);
			}
		}
	}

}